﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SimpleModel.Context;
using SimpleModel.Model;
using SimpleModel.DAL;
using System.Data.Common;
using System.Configuration;
using System.Diagnostics;
using Dapper;
using ProtoBuf;
using SimpleInfrastructure.Exceptions;
using SimpleInfrastructure.Serialize;
using SimpleModel.Cache.Redis;
using StackExchange.Redis;
using SimpleInfrastructure.Log;
using SimpleInfrastructure.Message;
using SimpleInfrastructure.Extentions;
using SimpleInfrastructure.FrameWorks;
using SimpleInfrastructure.Helpers;

namespace SimpleUse
{
    public partial class Form1 : Form
    {
        static readonly string get_id_sql = "select @@identity";
        public Form1()
        {
            InitializeComponent();
        }

        private void btnDB_Click(object sender, EventArgs e)
        {
            using (MDBContext context = new MDBContext())
            {
                var classinfos = context.Set<classinfo>().ToList();
            }
        }

        class teacher_class_map
        {
            public int teacher_id { set; get; }

            public int classinfo_id { set; get; }
        }
        private void btnDrapper_Click(object sender, EventArgs e)
        {
            InitTeacher();
        }

        private static void InitTeacher()
        {
            classinfo ci2 = new classinfo()
            {
                grade = 2017,
                name = "计算机二班"
            };
            classinfo ci3 = new classinfo()
            {
                grade = 2017,
                name = "计算机三班"
            };
            teacher t2 = new teacher()
            {
                age = 45,
                name = "胡老师",
                user_count = "t_002",
                password = "123456",
                sex = true
            };
            teacher t3 = new teacher()
            {
                age = 33,
                name = "林老师",
                user_count = "t_003",
                password = "123456",
                sex = false
            };
            string insert_classinfo_sql = "insert into classinfo(grade,name) values(@grade,@name)";
            string insert_user_sql =
                "insert into consumer(name,user_count,password,age,sex,phone,email) values(@name,@user_count,@password,@age,@sex,@phone,@email)";
            string insert_teacher_sql = "insert into teacher(id) values(@id)";
            string insert_teacher_class_map_sql =
                "insert into teacher_class_map(teacher_id,classinfo_id) values(@teacher_id,@classinfo_id)";
            using (var conn = SqlBuilder.GetBuilder().CreateConnection())
            {
                conn.Open();
                var tran = conn.BeginTransaction();
                try
                {
                    conn.Execute(insert_classinfo_sql, ci2, tran);
                    var cid2 = conn.ExecuteScalar<int>(get_id_sql, transaction: tran);
                    conn.Execute(insert_classinfo_sql, ci3, tran);
                    var cid3 = conn.ExecuteScalar<int>(get_id_sql, transaction: tran);
                    conn.Execute(insert_user_sql, t2, tran);
                    var tid2 = conn.ExecuteScalar<int>(get_id_sql, transaction: tran);
                    conn.Execute(insert_user_sql, t3, tran);
                    var tid3 = conn.ExecuteScalar<int>(get_id_sql, transaction: tran);
                    conn.Execute(insert_teacher_sql, new {id = tid2}, tran);
                    conn.Execute(insert_teacher_sql, new {id = tid3}, tran);
                    List<teacher_class_map> teacher_class_maps = new List<teacher_class_map>()
                    {
                        new teacher_class_map() {classinfo_id = cid2, teacher_id = tid2},
                        new teacher_class_map() {classinfo_id = cid3, teacher_id = tid2},
                        new teacher_class_map() {classinfo_id = cid2, teacher_id = tid3},
                        new teacher_class_map() {classinfo_id = cid3, teacher_id = tid3}
                    };
                    conn.Execute(insert_teacher_class_map_sql, teacher_class_maps, tran);
                    tran.Commit();
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
        }

        private static void InitStudent()
        {
            classinfo ci = new classinfo()
            {
                grade = 2017,
                name = "计算机一班"
            };
            student s1 = new student()
            {
                age = 19,
                classinfo = ci,
                name = "张三",
                user_count = "stu_001",
                password = "123456",
                sex = true
            };
            student s2 = new student()
            {
                age = 20,
                classinfo = ci,
                name = "李四",
                user_count = "stu_002",
                password = "123456",
                sex = false
            };
            student s3 = new student()
            {
                age = 19,
                classinfo = ci,
                name = "王五",
                user_count = "stu_003",
                password = "123456",
                sex = true
            };
            List<student> slist = new List<student>() {s1, s2, s3};
            string insert_classinfo_sql = "insert into classinfo(grade,name) values(@grade,@name)";
            string insert_user_sql =
                "insert into consumer(name,user_count,password,age,sex,phone,email) values(@name,@user_count,@password,@age,@sex,@phone,@email)";
            string insert_student_sql = "insert into student(id,classinfo_id) values(@id,@classinfo_id)";
            
            using (var conn = SqlBuilder.GetBuilder().CreateConnection())
            {
                conn.Open();
                var tran = conn.BeginTransaction();
                try
                {
                    int rows1 = conn.Execute(insert_classinfo_sql, ci, tran);
                    var id = conn.ExecuteScalar<int>(get_id_sql, transaction: tran);
                    s1.classinfo_id = s2.classinfo_id = s3.classinfo_id = id;
                    foreach (var stu in slist)
                    {
                        conn.Execute(insert_user_sql, stu, tran);
                        id = conn.ExecuteScalar<int>(get_id_sql, transaction: tran);
                        conn.Execute(insert_student_sql, new {id, stu.classinfo_id}, tran);
                    }
                    tran.Commit();
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
        }

        private void btnDuse_Click(object sender, EventArgs e)
        {
            using (var conn = SqlBuilder.GetBuilder().CreateConnection())
            {
                string query = "select * from classinfo";
                string query_teacher = "select c.* from teacher_class_map e join teacher t on e.teacher_id = t.id join consumer c on t.id=c.id where e.classinfo_id = @id";
                var classes = conn.Query<classinfo>(query);
                if (classes != null && classes.Any())
                {
                    foreach (var mclass in classes)
                    {
                        var teachers = conn.Query<teacher>(query_teacher, mclass);
                        if (teachers != null && teachers.Any())
                        {
                            mclass.teachers = teachers.ToList();
                        }
                    }
                    foreach (var mclass in classes)
                    {
                        List<string> tnames = new List<string>();
                        if (mclass.teachers != null && mclass.teachers.Any())
                        {
                            tnames = mclass.teachers.Select(t => t.name).ToList();
                        }
                        MessageBox.Show(string.Format("class:{0};teachers:{1}", mclass.name,string.Join(",", tnames)));
                    }
                }
            }
        }

        private static void StudentUse()
        {
            using (var conn = SqlBuilder.GetBuilder().CreateConnection())
            {
                string query_classinfo = "select * from classinfo";
                string query_student =
                    "select c.*,s.classinfo_id from consumer c join student s on c.id=s.id where s.classinfo_id = @classinfo_id";
                List<string> class_names = new List<string>();
                List<string> student_names = new List<string>();
                var classinfos = conn.Query<classinfo>(query_classinfo);
                if (classinfos != null && classinfos.Any())
                {
                    foreach (var classinfo in classinfos)
                    {
                        var students = conn.Query<student>(query_student, new {classinfo_id = classinfo.id});
                        if (students != null && students.Any())
                        {
                            foreach (var student in students)
                            {
                                student_names.Add(student.name);
                            }
                        }
                        if (student_names.Count > 0)
                            MessageBox.Show(string.Join(",", student_names) + string.Format(",classinfo_id:{0}", classinfo.id));
                    }
                }
            }
        }

        private Process pmain = null;
        private void btnrediserver_Click(object sender, EventArgs e)
        {
            string wrap_exe_name = ConfigurationManager.AppSettings["wrap_exe_name"];
            string wrap_exe_paras = ConfigurationManager.AppSettings["wrap_exe_paras"];
            try
            {
                pmain = new Process();
                pmain.StartInfo.FileName = wrap_exe_name;
                pmain.StartInfo.Arguments = wrap_exe_paras;
                pmain.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnend_Click(object sender, EventArgs e)
        {
            try
            {
                if (pmain != null && !pmain.HasExited)
                {
                    pmain.Kill();
                    pmain.WaitForExit();
                    pmain.Dispose();
                    pmain = null;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        [Serializable]
        [ProtoContract]
        class FormPerson
        {
            [ProtoMember(1)]
            public string Name { set; get; }

            [ProtoMember(2)]
            public int Age { set; get; }

            [ProtoMember(3)]
            public double Score { set; get; }
        }

        private void btnserialize_Click(object sender, EventArgs e)
        {
            Random r = new Random();
            //List<FormPerson> persons = new List<FormPerson>();
            //for (int i = 0; i < 100000; i++)
            //{
            //    FormPerson ptemp = new FormPerson() {Age = r.Next(15,45),Name="aa",Score = r.NextDouble()*100};
            //    persons.Add(ptemp);
            //}
            ISerializer json_serializer = new NJsonSerializer();
            ISerializer protobuf_serializer = new ProtoBufSerializer();
            ISerializer binary_serializer = new BinarySerializer();
            //TestSerializer(ps=> json_serializer.Serialize(ps), persons,"json");
            //TestSerializer(ps => protobuf_serializer.Serialize(ps), persons, "proto");
            //TestSerializer(ps => binary_serializer.Serialize(ps), persons, "binary");
            FormPerson ptemp1 = new FormPerson() { Age = r.Next(15, 45), Name = "aa", Score = r.NextDouble() * 100 };
            var json_bytes = Encoding.Default.GetBytes(json_serializer.Serialize(ptemp1));
            var proto_bytes = protobuf_serializer.Serialize(ptemp1);
            var binary_bytes = binary_serializer.Serialize(ptemp1);
            MessageBox.Show(string.Format("json:{0}bytes,proto:{1}bytes,binary:{2}bytes", json_bytes.Length, proto_bytes.Length, binary_bytes.Length));
        }

        private static void TestSerializer(Action<List<FormPerson>> funcAction, List<FormPerson> persons, string serializer_type)
        {
            int aaStart = System.Environment.TickCount;
            funcAction(persons);
            MessageBox.Show(string.Format("{0}序列化耗时{1}毫秒", serializer_type, System.Environment.TickCount - aaStart));
        }

        private void butredisval_Click(object sender, EventArgs e)
        {
            //Random r = new Random();
            //FormPerson ptemp1 = new FormPerson() { Age = r.Next(15, 45), Name = "aa", Score = r.NextDouble() * 100 };
            //var serializer = SerializerProvider.GetSerializer(ptemp1);
            //var val = serializer.Serialize(ptemp1);
            //FormPerson ptemp2 = serializer.Deserialize<FormPerson>(val);
            //MessageBox.Show(ptemp2.Name);
            Exception ex = new ArgumentException("a not fount");
            var Detail = new ExceptionMsg(ex);
            var serializer1 = SerializerProvider.GetSerializer(Detail);
            NotifyInfo info = new NotifyInfo() {Dst = "aaa",Src = "bbb",Message = "test",NotifyType = NotifyType.Error,DetailString = serializer1.Serialize(Detail)};
            var serializer2 = SerializerProvider.GetSerializer(info);
            var val = serializer2.Serialize(info);
            NotifyInfo info2 = serializer2.Deserialize<NotifyInfo>(val);
            var Dtail2 = serializer1.Deserialize<ExceptionMsg>(info2.DetailString);
            MessageBox.Show(Dtail2.Message);
        }

        private void btnredis_Click(object sender, EventArgs e)
        {
            Random r = new Random();
            //FormPerson ptemp1 = new FormPerson() { Age = r.Next(15, 45), Name = "aa", Score = r.NextDouble() * 100 };
            //var s1 = ptemp1.Score;
            //StackExchangeRedisHelper.Set("test", ptemp1);
            //FormPerson ptemp2 = StackExchangeRedisHelper.Get<FormPerson>("test");
            //var s2 = ptemp2.Score;
            //MessageBox.Show(string.Format("prior:{0},posterior:{1}",s1,s2));
            //string key = "aaa";
            //StackExchangeRedisHelper.Increment(key);
            //int k1 = StackExchangeRedisHelper.Get<int>(key);
            //StackExchangeRedisHelper.Increment(key);
            //StackExchangeRedisHelper.Increment(key);
            //StackExchangeRedisHelper.Increment(key);
            //int k2 = StackExchangeRedisHelper.Get<int>(key);
            //StackExchangeRedisHelper.Decrement(key);
            //int k3 = StackExchangeRedisHelper.Get<int>(key);
            //MessageBox.Show(string.Format("k1:{0},k2:{1},k3:{2}", k1, k2, k3));
            string channel = "aaat";
            FormPerson ptemp = new FormPerson() { Age = r.Next(15, 45), Name = "aa", Score = r.NextDouble() * 100 };
            StackExchangeRedisHelper.Subscribe<FormPerson>(channel, handle_msg);
            StackExchangeRedisHelper.Publish(channel, ptemp);
        }

        private void handle_msg(string channel,FormPerson person)
        {
            MessageBox.Show(channel+":"+person.Name);
        }

        private void btnlog_Click(object sender, EventArgs e)
        {
            ILogger logger = FileLogger.Instance;
            logger.Log(LogLevel.Error,new Exception("TEST"),"{0}:{1}","liyan",24);
        }

        private void btnSys_Click(object sender, EventArgs e)
        {
            MessageBox.Show(EnvHelper.GetCpuCoreCount().ToString());
        }
    }
}
